package com.Hermes.User;

import com.Hermes.Omega.SK;
import edu.biu.scapi.exceptions.FactoriesException;
import edu.biu.scapi.primitives.hash.CryptographicHash;
import edu.biu.scapi.primitives.hash.bc.BcSHA256;
import edu.biu.scapi.primitives.prf.PseudorandomFunction;
import edu.biu.scapi.primitives.prf.PseudorandomPermutation;
import edu.biu.scapi.primitives.prf.bc.BcHMAC;
import edu.biu.scapi.tools.Factories.PrfFactory;

import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public  class PRF_PRP_Hash {
    private final PseudorandomFunction prfF3;
    private final PseudorandomFunction prfF4;
    private final PseudorandomPermutation prpT1;
    private final PseudorandomPermutation prpT2;
    private final BcHMAC H1;
    private final CryptographicHash H2;



    public PRF_PRP_Hash(int sksize, SK sk) throws FactoriesException, InvalidKeyException, NoSuchAlgorithmException {
        prpT2 = (PseudorandomPermutation) PrfFactory.getInstance().getObject("PrpFromPrfVarying");
        prpT1 = (PseudorandomPermutation) PrfFactory.getInstance().getObject("PrpFromPrfVarying");
        prfF4 = PrfFactory.getInstance().getObject("HMac(SHA-256)");
        prfF3 = PrfFactory.getInstance().getObject("HMac(SHA-256)");

        SecretKey k1 = prpT1.generateKey(sksize);
        SecretKey k2 = prpT2.generateKey(sksize);
        SecretKey k3 = prfF3.generateKey(sksize);
        SecretKey k4 = prfF4.generateKey(sksize);
        prpT1.setKey(k1);
        prpT2.setKey(k2);
        prfF3.setKey(k3);
        prfF4.setKey(k4);
        sk.set_K(k1, k2, k3, k4);
//        System.out.println(k1);
//        System.out.println(k2);
//        System.out.println(k3);
//        System.out.println(k4);

        H1 = new BcHMAC("SHA-256");
        SecretKey shk1 = H1.generateKey(256);
        H1.setKey(shk1);
        H2 = new BcSHA256();

    }

//    public static void main(String[] args) throws FactoriesException, NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException {
//        SK sk = new SK();
//        PRF_PRP_Hash pph = new PRF_PRP_Hash(256, sk);
//        byte[] s=new byte[16];
//        s=new BigInteger("4645").toByteArray();
////        byte[] res=new byte[20];//PRF:HMac(SHA-1)输出长度必须固定为20
//        byte[] res=new byte[s.length];//PRP:in.len==out.len且为偶数
////        byte[] res=new byte[32];//SHA256输出必须是32
//            pph.use_T2(s,res);
////        byte[] res = pph.use_H1(s);
//        for (int i = 0; i < res.length; i++) {
//            System.out.print(res[i]);
//        }
//        System.out.println();
//        System.out.println(new BigInteger(res));
//    }

    public void use_T1(byte[] in, byte[] out) throws IllegalBlockSizeException {
        prpT1.computeBlock(in, 0, in.length, out, 0, out.length);

    }

    public void use_T2(byte[] in, byte[] out)  {
//        for (int i = 0; i < out.length; i++) {
//
//            System.out.print(out[i]);
//        }
//        System.out.println();
        try {
            prpT2.computeBlock(in, 0, in.length, out, 0, out.length);
        } catch (IllegalBlockSizeException e) {
            System.out.println("in.length = " + in.length);
            e.printStackTrace();


        }
//        for (int i = 0; i < out.length; i++) {
//
//            System.out.print(out[i]);
//        }

    }

    public void use_F3(byte[] in, byte[] out) throws IllegalBlockSizeException {
//        for (int i = 0; i < out.length; i++) {
//
//            System.out.print(out[i]);
//        }
//        System.out.println();
        prfF3.computeBlock(in, 0, in.length, out, 0, 32);
//        for (int i = 0; i < out.length; i++) {
//
//            System.out.print(out[i]);
//        }
    }

    public void use_F4(byte[] in, byte[] out) throws IllegalBlockSizeException {
        prfF4.computeBlock(in, 0,in.length, out, 0,32);
    }

    public byte[] use_H1(byte[] msg) {//BcHMAC("SHA-256")
        return H1.mac(msg, 0, msg.length);
    }

    public void use_H2(byte[] msg, byte[] tag) {    //BcSHA256

//        for (int i = 0; i < tag.length; i++) {
//            System.out.print(tag[i]);
//        }
//        System.out.println();
        H2.update(msg, 0, msg.length);
        H2.hashFinal(tag, 0);
//        for (int i = 0; i < tag.length; i++) {
//            System.out.print(tag[i]);
//        }
    }

    public void setKey_T1(SecretKey sk) throws InvalidKeyException {
        prpT1.setKey(sk);
    }

    public void setKey_T2(SecretKey sk) throws InvalidKeyException {
        prpT2.setKey(sk);
    }

    public void setKey_F3(SecretKey sk) throws InvalidKeyException {
        prfF3.setKey(sk);
    }

    public void setKey_F4(SecretKey sk) throws InvalidKeyException {
        prfF4.setKey(sk);
    }
}
